package com.nwpu.coursesupport.service.imple;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.nwpu.coursesupport.criteria.ClassStudentSearchCriteria;
import com.nwpu.coursesupport.criteria.TaskSearchCriteria;
import com.nwpu.coursesupport.entity.ClassStudent;
import com.nwpu.coursesupport.entity.Course;
import com.nwpu.coursesupport.entity.Task;
import com.nwpu.coursesupport.entity.bean.JSONResult;
import com.nwpu.coursesupport.enumeration.ClassType;
import com.nwpu.coursesupport.enumeration.RoleType;
import com.nwpu.coursesupport.enumeration.Status;
import com.nwpu.coursesupport.enumeration.TaskType;
import com.nwpu.coursesupport.exception.GenGradeException;
import com.nwpu.coursesupport.mapper.ClassMapper;
import com.nwpu.coursesupport.mapper.ClassStudentMapper;
import com.nwpu.coursesupport.mapper.CourseMapper;
import com.nwpu.coursesupport.mapper.TaskMapper;
import com.nwpu.coursesupport.service.AbstractService;
import com.nwpu.coursesupport.service.GenGradeService;
import com.nwpu.coursesupport.service.param.CalculateGradeParam;
import com.nwpu.coursesupport.service.param.CalculateGradeParam.UpdateGradeParam;
import com.nwpu.coursesupport.service.param.GenGradeServiceParam;
import com.nwpu.coursesupport.service.param.IDParam;
import com.nwpu.coursesupport.tool.UpdateUtil;
import com.nwpu.coursesupport.view.CourseGradeRateView;
import com.nwpu.coursesupport.view.GradeRateItem;
import com.nwpu.coursesupport.view.TaskGradeView;
import com.nwpu.coursesupport.view.criteria.TaskGradeViewSearchCriteria;
import com.nwpu.coursesupport.view.criteria.UpdateGradeStatusSearchCriteria;
import com.nwpu.coursesupport.view.mapper.TaskGradeViewMapper;

@Service("genGradeService")
@Transactional
public class GenGradeServiceImple extends AbstractService implements GenGradeService {

	@Autowired
	private CourseMapper courseMapper;
	@Autowired
	private TaskMapper taskMapper;
	@Autowired
	private ClassMapper classMapper;
	@Autowired
	private TaskGradeViewMapper taskGradeViewMapper;
	@Autowired
	private ClassStudentMapper classStudentMapper;
	
	protected static Logger logger = LoggerFactory.getLogger(GenGradeServiceImple.class);


	public JSONResult getCourseRate(IDParam p) throws Exception {
		JSONResult rst = new JSONResult();
		rst.fail();

		if (p == null || p.getId() <= 0) {
			logger.error("参数有误");
			return rst.fail("参数有误");
		}

		CourseGradeRateView view = this.courseMapper.getRate(p.getId());

		if (view == null) {
			logger.error("该课程不存在");
			return rst.fail("该课程不存在");
		}
		rst.addData("view", view);
		rst.addData("courseId", p.getId());
		rst.success();
		return rst;
	}

	public JSONResult updateCourseRate(CourseGradeRateView view) throws Exception {
		JSONResult rst = new JSONResult();
		rst.fail();

		if (view == null || view.getId() <= 0) {
			logger.error("参数有误");
			return rst.fail("参数有误");
		}

		Course course = this.courseMapper.findById(view.getId());
		if (course == null) {
			logger.error("该课程不存在");
			return rst.fail("该课程不存在");
		}

		if (UpdateUtil.setValues(course, view) > 0) {
			if (!this.courseMapper.updateRate(course)) {
				logger.error("修改失败");
				return rst.fail("修改失败");
			}
		}

		rst.success();
		return rst;
	}

	public JSONResult getTaskList(IDParam p) throws Exception {
		JSONResult rst = new JSONResult();
		rst.fail();

		if (p == null || p.getId() <= 0) {
			logger.error("参数错误");
			return rst.fail("参数错误");
		}

		TaskSearchCriteria sc = new TaskSearchCriteria();
		sc.setCourseId(p.getId());

		sc.setType(TaskType.HOMEWORK);
		List<Task> homeworkList = this.taskMapper.findAssignTaskByCourseId(sc);
		rst.addData("homeworkList", homeworkList);

		sc.setType(TaskType.LABTEST);
		List<Task> labList = this.taskMapper.findAssignTaskByCourseId(sc);
		rst.addData("labList", labList);

		sc.setType(TaskType.TESTINLESSON);
		List<Task> testInLessonList = this.taskMapper.findAssignTaskByCourseId(sc);
		rst.addData("testInLessonList", testInLessonList);

		rst.success();
		return rst;
	}

	public JSONResult updateTaskGradeStatus(GenGradeServiceParam p) throws GenGradeException {
		JSONResult rst = new JSONResult();
		rst.fail();

		if (p == null || p.getCourseId() <= 0 || p.getItem() == null || p.getItem().size() <= 0) {
			logger.error("参数错误");
			return rst.fail("参数错误");
		}

		Course course = this.courseMapper.findById(p.getCourseId());
		if (course == null) {
			logger.error("该课程不存在");
			return rst.fail("该课程不存在");
		}

		TaskSearchCriteria sc = new TaskSearchCriteria();
		sc.setCourseId(p.getCourseId());
		sc.setIsAddToGrade(Status.YES);

		List<GradeRateItem> itmes = this.taskMapper.gradeRateView(sc);
		if (CollectionUtils.isEqualCollection(itmes, p.getItem())) {
			return rst.success();
		}

		UpdateGradeStatusSearchCriteria usc = new UpdateGradeStatusSearchCriteria();
		usc.setCourseId(p.getCourseId());
		usc.setStatus(Status.NO);

		if (!this.taskMapper.updateGradeStatus(usc)) {
			logger.error("生成成绩失败,并抛出异常GenGradeException");
			throw new GenGradeException();
		}

		for (GradeRateItem item : p.getItem()) {
			usc.setId(item.getId());
			usc.setRadio(item.getRate());
			usc.setStatus(Status.YES);
			if (!this.taskMapper.updateGrade(usc)) {
				logger.error("生成成绩失败,并抛出异常GenGradeException");
				throw new GenGradeException();
			}
		}
		rst.success();
		return rst;
	}

	public JSONResult genTaskGrade(IDParam p) throws GenGradeException {
		JSONResult rst = new JSONResult();
		rst.fail();

		if (p == null || p.getId() <= 0) {
			logger.error("参数有误");
			return rst.fail("参数有误");
		}
		Course course = this.courseMapper.findById(p.getId());
		if (course == null) {
			logger.error("该课程不存在");
			return rst.fail("该课程不存在");
		}

		TaskGradeViewSearchCriteria sc = new TaskGradeViewSearchCriteria();
		sc.setCourseId(p.getId());
		sc.setIsAddToGrade(Status.YES);
		sc.setRoleType(RoleType.STUDENT);
		sc.setTaskType(TaskType.TASKMAIN);
		
		//计算任务成绩
		List<TaskGradeView> taskGrades = this.taskGradeViewMapper.genTaskGrade(sc);
		if (taskGrades.size() <= 0) {
			logger.error("生成任务成绩失败");
			return rst.fail("生成任务成绩失败");
		}//相关同学的所有成绩
		
		
		//计算平时成绩(当堂提问平均值)
		sc = new TaskGradeViewSearchCriteria();
		sc.setCourseId(p.getId());
		List<TaskGradeView> dailyGrades = this.taskGradeViewMapper.genDailyGrade(sc);
		
		
		ClassStudent cs = null;
		TaskGradeView taskGrade=null;
		TaskGradeView dailyGrade = null;
		
		Date updateTime = new Date();
		int id = (int) getSession().getAttribute("id");
		String name = (String) getSession().getAttribute("name");
		RoleType roleType = (RoleType) getSession().getAttribute("roleType");
		
		//获得课程的所有同学
		ClassStudentSearchCriteria csc = new ClassStudentSearchCriteria();
		List<ClassStudent> results = new ArrayList<ClassStudent>();
		csc.setCourseId(p.getId());
		csc.setClassType(ClassType.CLASS);
		List<ClassStudent> source = this.classStudentMapper.getGradeItem(csc);
		
		
		for (int i = 0; i < source.size(); i++) {

			cs =source.get(i);
			//该学生的任务成绩
			taskGrade = findItem(cs.getStudentId(), i, taskGrades);
			if(taskGrade==null){
				cs.setTaskTotalGrade(0);
			}else if(taskGrade.getScore() > 100){
				cs.setTaskTotalGrade(100);
			}else{
				cs.setTaskTotalGrade(taskGrade.getScore());
			}
			//该学生的平时成绩
			dailyGrade = findItem(cs.getStudentId(),i,dailyGrades);
			if(dailyGrade == null){
				cs.setDailyGrade(0);
			}else if(dailyGrade.getScore() > 100){
				cs.setDailyGrade(100);
			}else{
				cs.setDailyGrade(dailyGrade.getScore());
			}
			
			//计算总成绩
			double totalGrade = cs.getTaskTotalGrade() * course.getTaskGradeRatio()/100
					+ cs.getDailyGrade() * course.getDailyGradeRatio()/100
					+ cs.getLabTestGrade() * course.getLabGradeRatio()/100
					+ cs.getTheoryTestGrade() * course.getTheoryGradeRatio()/100;
			cs.setFinalTotalGrade(totalGrade);
			cs.setUpdateDate(updateTime);
			cs.setUpdateOperatorId(id);
			cs.setUpdateOperatorName(name);
			cs.setRoleType(roleType);
			results.add(cs);
		}
		
		try {
			this.classStudentMapper.batchUpdate(results);
		} catch (Exception e) {
			logger.error("批量修改学生成绩失败,并抛出异常GenGradeException");
			throw new GenGradeException("批量修改学生成绩失败");
		}

		rst.success();
		return rst;
	}

	private TaskGradeView findItem(int uid, int index, List<TaskGradeView> list) {
		if (index < 0 || index >= list.size()) {
			return null;
		}
		TaskGradeView item = list.get(index);
		if (item.getUid() == uid) {
			return item;
		} else if (item.getUid() < uid) {
			for (int i = index + 1; i < list.size(); i++) {
				item = list.get(i);
				if (item.getUid() == uid) {
					return item;
				} else if (item.getUid() > uid) {
					return null;
				}
			}
		} else {
			for (int i = index - 1; i >= 0; i--) {
				item = list.get(i);
				if (item.getUid() == uid) {
					return item;
				} else if (item.getUid() < uid) {
					return null;
				}
			}
		}
		return null;
	}

	public JSONResult batchUpdateGrade(CalculateGradeParam.BatchUpdateGradeParam p) throws GenGradeException {
		JSONResult rst = new JSONResult();
		rst.fail();

		if (p == null || p.getCourseId() <= 0 || p.getList() == null || p.getList().size() <= 0) {
			logger.error("参数有误");
			return rst.fail("参数有误");
		}
		Course course = this.courseMapper.findById(p.getCourseId());
		if (course == null) {
			logger.error("该课程不存在");
			return rst.fail("该课程不存在");
		};

		ClassStudent cs = null;

		Date updateTime = new Date();
		int id = (int) getSession().getAttribute("id");
		String name = (String) getSession().getAttribute("name");
		RoleType roleType = (RoleType) getSession().getAttribute("roleType");
		List<ClassStudent> results = new ArrayList<ClassStudent>();
		for (UpdateGradeParam item : p.getList()) {
			cs = this.classStudentMapper.findById(item.getId());
			if (cs == null) {
				logger.error("该记录不存在");
				return rst.fail("该记录不存在");
			}
			if (UpdateUtil.setValues(cs, item) > 0) {
				double totalGrade = cs.getTaskTotalGrade() * course.getTaskGradeRatio()/100
						+ cs.getDailyGrade() * course.getDailyGradeRatio()/100
						+ cs.getLabTestGrade() * course.getLabGradeRatio()/100
						+ cs.getTheoryTestGrade() * course.getTheoryGradeRatio()/100;
				cs.setFinalTotalGrade(totalGrade);
				cs.setUpdateDate(updateTime);
				cs.setUpdateOperatorId(id);
				cs.setUpdateOperatorName(name);
				cs.setRoleType(roleType);

				results.add(cs);
			}
		}
		if(results.size()<=0){
			return rst.success();
		}
		try {
			this.classStudentMapper.batchUpdate(results);
		} catch (Exception e) {
			logger.error("批量修改成绩失败,并抛出异常GenGradeException");
			throw new GenGradeException("批量修改成绩失败");
		}
		rst.success();
		return rst;
	}

	public JSONResult updateGrade(CalculateGradeParam.UpdateGradeParam p) throws Exception {
		JSONResult rst = new JSONResult();
		rst.fail();

		if (p == null || p.getId() <= 0) {
			logger.error("参数有误");
			return rst.fail("参数有误");
		}

		ClassStudent cs = this.classStudentMapper.findById(p.getId());
		if (cs == null) {
			logger.error("该记录不存在");
			return rst.fail("该记录不存在");
		}

		Course course = this.courseMapper.findById(cs.getCourseId());

		Date updateTime = new Date();
		int id = (int) getSession().getAttribute("id");
		String name = (String) getSession().getAttribute("name");
		RoleType roleType = (RoleType) getSession().getAttribute("roleType");
		if (UpdateUtil.setValues(cs, p) > 0) {
			double totalGrade = cs.getTaskTotalGrade() * course.getTaskGradeRatio()/100
					+ cs.getDailyGrade() * course.getDailyGradeRatio()/100
					+ cs.getLabTestGrade() * course.getLabGradeRatio()/100
					+ cs.getTheoryTestGrade() * course.getTheoryGradeRatio()/100;
			cs.setFinalTotalGrade(totalGrade);
			cs.setUpdateDate(updateTime);
			cs.setUpdateOperatorId(id);
			cs.setUpdateOperatorName(name);
			cs.setRoleType(roleType);
			if (!this.classStudentMapper.update(cs)) {
				logger.error("修改失败");
				return rst.fail("修改失败");
			}
		}
		rst.success();
		return rst;
	}
}
